#include "bootpack.h"
#include "package.h"
/*
struct DHCP_DISCOVER{
    unsigned char op;
    unsigned char htype;
    unsigned char hlen;
    unsigned char hops;
    unsigned int xid;
    short secs;
    short flag;
    long ciaddr;
    long yiaddr;
    long siaddr;
    long giaddr;
    unsigned char[16] chaddr;
    unsigned char[64] sname;
    unsigned char[128] file;
    struct DHCP_OPTIONS *options;
};
struct DHCP_OPTIONS{
    unsigned char type;
    unsigned char length;
    unsigned char *value;
};

*/
/*
void init_dhcp_options(struct MEMMAN *memman,struct DHCP_OPTIONS *options){
    //struct DHCP_OPTIONS options_array[7]
    options=(unsigned char *)memman_alloc_4k(memman,64);
        {51,1,{1}},
        {61,7,{1,0x52,0x54,0x00,0x12,0x34,0x56}},
        {50,4,{192,168,1,5},
        {12,15,{'z','m','m'}},
        {60,8,{'r','l','k'}},
        {55,12,{1,25,3,6,44,46,47,31,33,121,249,43}},
        {255,255,{}},
    };
}
*/

void init_message_package(DHCP_MESSAGE * dd,DHCP_INFO * dhcp_info){
    dd->op=1;
    dd->htype=1;
    dd->hlen=6;
    dd->hops=0;
    dd->xid=0x83208856;
    dd->secs=0;
    dd->flag=0;
    dd->ciaddr=dhcp_info->your_ip_addr;
    dd->yiaddr=0;
    dd->siaddr=0;
    dd->giaddr=0;
    dd->chaddr[5]=GetRegisterValue(1,6);
    dd->chaddr[4]=GetRegisterValue(1,5);
    dd->chaddr[3]=GetRegisterValue(1,4);
    dd->chaddr[2]=GetRegisterValue(1,3);
    dd->chaddr[1]=GetRegisterValue(1,2);
    dd->chaddr[0]=GetRegisterValue(1,1);
    int i;
    //dd->sname=(unsigned char *)memman_alloc_4k(memman,64);
    for(i=0;i<64;i++)
        dd->sname[i]=0;
    for(i=0;i<128;i++)
        dd->file[i]=0;
    //dd->file=(unsigned char *)memman_alloc_4k(memman,128);
    dd->magic_cookie[0]=0x63;
    dd->magic_cookie[1]=0x82;
    dd->magic_cookie[2]=0x53;
    dd->magic_cookie[3]=0x63;
    //dd->options=options;
    uchar *yip = (uchar *)(&(dhcp_info->your_ip_addr));
    unsigned char options[44]={
        0x35,0x01,dhcp_info->message_type,//3
        61,7,1,GetRegisterValue(1,1),GetRegisterValue(1,2),GetRegisterValue(1,3),GetRegisterValue(1,4),GetRegisterValue(1,5),GetRegisterValue(1,6),//9
        50,4,yip[0],yip[1],yip[2],yip[3],//6
        12,3,'z','m','m',//5
        60,3,'r','l','k',//5
        55,14,1,3,6,15,31,33,43,44,46,47,119,121,249,252//16
    };
    
    for(i=0;i<44;i++){
        dd->options[i]=options[i];
    }
    for(i=0;i<10;i++){
        dd->end[i]=0x00;
    }
    dd->end[0]=0xff;


}

short calculate_checksum(short* buffer, int bytes)
{
    short checksum = 0;
    short * end = buffer + bytes;

    // odd bytes add last byte and reset end
    if (bytes % 2 == 1) {
        end = buffer + bytes - 1;
        checksum += (*end) << 8;
    }

    // add words of two bytes, one by one
    while (buffer < end) {
        checksum += buffer[0] << 8;
        checksum += buffer[1];
        buffer += 2;
    }

    // add carry if any
    short carray = checksum >> 16;
    while (carray) {
        checksum = (checksum & 0xffff) + carray;
        carray = checksum >> 16;
    }

    // negate it
    checksum = ~checksum;

    return checksum & 0xffff;
}

void init_ip_package(IP_HEADER * header){
    /*
    unsigned char ip_and_headlength;
    unsigned char service_level;
    short length;
    short identify;
    short label_and_offset;
    unsigned char    ttl;
    unsigned char protocal;
    short head_checksum;
    long src_ip;
    long dst_ip;
    struct UDP_PACKAGE udp;
    */
    header->ip_and_headlength=0x45;
    header->service_level=0x00;
    //header->length=(sizeof(IP_PACKAGE)&0xff00)>>8 + (sizeof(IP_PACKAGE)&0xff)<<8;
    header->length=hxl(sizeof(IP_PACKAGE)-4);
    //header->length=sizeof(IP_PACKAGE)-4;

    header->identify=0x3333;
    header->label_and_offset=hxl(0x1<<14);// 不分段
    header->ttl=0x80;//生存时间设置为最大
    header->protocal=17;// 协议号是10进制的
    header->head_checksum=0;
    header->src_ip=0x00000000;
    header->dest_ip=0xffffffff;
}
void init_mac_header(MAC_PACKAGE *mac,unsigned short protocol){
    /*unsigned char dest_mac[6];
    unsigned char src_mac[6];
    short type;
    struct IP_PACKAGE ip;
    */
    unsigned char dest_mac[6]={0xff,0xff,0xff,0xff,0xff,0xff};
    unsigned char src_mac[6]={0x52,0x54,0x00,0x12,0x34,0x56};
    int i;
    for(i=0;i<6;i++){
        mac->header.dest_mac[i]=dest_mac[i];
        mac->header.src_mac[i]=GetRegisterValue(1,i+1);
    }
    mac->header.pre=0xff;
    //mac->header.protocal=hxl(0x0800);
    mac->header.protocal=hxl(protocol);

}
void init_arp_packet(ARP_PACKET *arpp,DHCP_INFO * dhcp_info,IP_ADDR * ipa,MAC_ADDR * maca){
    /*
    unsigned short hardware_type;
    unsigned short protocol_type;
    uchar hardware_address_length;
    uchar protocol_address_length;
    unsigned short operation_code;
    uchar sender_mac[6];
    uchar sender_ip[4];
    uchar target_mac[6];
    uchar target_ip[4];
    */
    arpp->hardware_type=hxl(0x0001);
    arpp->protocol_type=hxl(0x0800);
    arpp->hardware_address_length=6;
    arpp->protocol_address_length=4;
    int i;
    for(i=0;i<6;i++){
        arpp->sender_mac[i]=GetRegisterValue(1,i+1);
        arpp->target_mac[i]=maca->addr[i];
    }
    for(i=0;i<4;i++){
        arpp->sender_ip[i]=((uchar *)(&(dhcp_info->your_ip_addr)))[i];
        arpp->target_ip[i]=ipa->addr[i];
    }
}
int show_package(unsigned char *buf_back,struct BOOTINFO *binfo,unsigned char * p,int length,int back_row,char * name,unsigned char * s){
    //unsigned char * p=(unsigned char*)(&(mac_p->ip));
    //sprintf(s,"ip:");
    //unsigned char s[40];
    int i;
    sprintf(s,"[%d]-[%d]-%s",back_row,length,name);
    int length_show=length;
    if(length_show>30)
        length_show=30;
    for(i=0;i<length_show;i++){
        sprintf(s,"%s%02x",s,p[i]);
    }
    sprintf(s,"%s<--->",s);
    for(i=0;i<1;i++){
        sprintf(s,"%s%02x",s,p[length-1-i]);
    }

    putfonts8_asc(buf_back, binfo->scrnx, 50, 350+back_row*16, COL8_FFFFFF, s);
    back_row++;
    return back_row;
}

void analysis_buff(FORSHOWINFO forshow,uchar *recv,uchar *s2){
    int i=-4;
    strshow("mac header:");
    sprintf(s2,"DEST MAC:%02x-%02x-%02x-%02x-%02x-%02x",recv[i+4],recv[i+5],recv[i+6],recv[i+7],recv[i+8],recv[i+9]);
    sprintf(s2,"%s,SRC MAC:%02x-%02x-%02x-%02x-%02x-%02x",s2,recv[i+10],recv[i+11],recv[i+12],recv[i+13],recv[i+14],recv[i+15]);
    //sprintf(s2,"%s,L:%d ",s2,*((unsigned short *)(recv+i+2)));
    strshow(s2);
                    
    // ip start at 18
    strshow("ip  header:");
    //sprintf(s2,"L:%d",*((unsigned char *)(recv+i+21))+(*(recv+i+20)<<8));
    sprintf(s2,"L:%d",(*(recv+i+21)) | (*(recv+i+20)<<8) );
    // 分段:ip_start+ 4,5,6,7
    // TTL: 8
    // Protocal:9
    uchar protocal = *(recv+i+27);
    sprintf(s2,"%s,PROTO:%d",s2,protocal);
    //buffshow(recv+i+27,1);// IP上层协议
    //Checksum: 10,11
    // src ip:12,13,14,15
    //buffshow(recv+i+30,4); src ip 
    // dest ip:16,17,18,19
    //buffshow(recv+i+34,4); dest ip
    sprintf(s2,"%s,SRC IP:%d.%d.%d.%d",s2,recv[i+30],recv[i+31],recv[i+32],recv[i+33]);
    sprintf(s2,"%s,DEST IP:%d.%d.%d.%d",s2,recv[i+34],recv[i+35],recv[i+36],recv[i+37]);
    strshow(s2);
    if(protocal==17){ // 如果是17，表明需要用UDP协议去解析数据
        strshow("udp header:");
        //sprintf(s2,"SRC PORT:%d",*((unsigned char *)(recv+i+39))+(*(recv+i+38)<<8));
        //sprintf(s2,"%s,DEST PORT:%d",s2,*((unsigned char *)(recv+i+41))+(*(recv+i+40)<<8));
        sprintf(s2,"SRC PORT:%d",hxl(*((unsigned short *)(recv+i+38))));
        sprintf(s2,"%s,DEST PORT:%d",s2,hxl(*((unsigned short *)(recv+i+40))));
        //length_udp=*((unsigned char *)(recv+i+43))+(*(recv+i+42)<<8);
        unsigned short length_udp=hxl(*((unsigned short *)(recv+i+42)));
        sprintf(s2,"%s,L:%d",s2,length_udp);
        strshow(s2);

        strshow("udp data:");
        buffshow(recv+i+46,length_udp-8);
    }
}
uchar* number2etherprototal(unsigned short protocal){
    //reference:https://en.wikipedia.org/wiki/EtherType
    switch(hxl(protocal)){
        case 0x0800:
            return "IPv4";
        case 0x0806:
            return "ARP";
        case 0x0842:
            return "Wake-on-LAN";
        case 0x22F0:
            return "AVTP";
        case 0x22F3:
            return "IETF TRILL Protocol";
        case 0x22EA:
            return "Stream Reservation Protocol";
        case 0x6002:
            return "DEC MOP RC";
        case 0x6003:
            return "DECnet";
        case 0x6004:
            return "DEC LAT";
        case 0x8035:
            return "RARP-Reverse Address Resolution Protocol";
        case 0x809B:
            return "AppleTalk-Ethertalk";
        case 0x80F3:
            return "AARP-AppleTalk Address Resolution Protocal";
        case 0x8100:
            return "VLAN0tagged frame and Shortest Path Bridging";
        case 0x8102:
            return "SLPP";
        case 0x8103:
            return "VLACP";
        case 0x8137:
            return "IPX";
        case 0x8204:
            return "QNX Qnet";
        case 0x86DD:
            return "IPv6";
        case 0x8808:
            return "Ethernet flow control";
        case 0x8809:
            return "LACP";
        case 0x8819:
            return "CobraNet";
        case 0x8847:
            return "MPLS unicast";
        case 0x8848:
            return "MPLS multicast";
        case 0x8863:
            return "PPPoE Discovery Stage";
        case 0x8864:
            return "PPPoE Session Stage";
        case 0x887B:
            return "HomePlug 1.0 MME";
        case 0x888E:
            return "EAP over LAN";
        case 0x8892:
            return "PROFINET";
        case 0x889A:
            return "HyperSCSI";
        case 0x88A2:
            return "ATA over Ethernet";
        case 0x88A4:
            return "EtherCAT Protocol";
        case 0x88A8:
            return "S-Tag";
        case 0x88AB:
            return "Ethernet Powerlink";
        case 0x88B8:
            return "GOOSE";
        case 0x88B9:
            return "GSE";
        case 0x88BA:
            return "SV";
        case 0x88BF:
            return "MikroTik RoMON";
        case 0x88CC:
            return "LLDP";
        case 0x88CD:
            return "SERCOS III";
        case 0x88E1:
            return "HomePlug Creen PHY";
        case 0x88E3:
            return "MACsec";
        case 0x88E5:
            return "PBB";
        case 0x88E7:
            return "PTP";
        case 0x88F8:
            return "NC-SI";
        case 0x88FB:
            return "PRP";
        case 0x8902:
            return "OAM";
        case 0x8906:
            return "FCoE";
        case 0x8914:
            return "FCoE Initialization Protocol";
        case 0x8915:
            return "RoCE";
        case 0x891D:
            return "TTE";
        case 0x893A:
            return "1905.1 IEEE Protocol";
        case 0x892F:
            return "HSR";
        case 0x9000:
            return "Ethernet Configuration Testing Protocol";
        case 0xF1C1:
            return "Redundancy Tag";
        default:
            return "unassigned";
    }    
}
uchar* number2ipprototal(uchar protocal){
    //uchar protocal_name[20];
    switch(protocal){
        case 0x00:
            return "HOPOPT";
        case 0x01:
            return "ICMP";
        case 0x02:
            return "IGMP";
        case 0x03:
            return "GGP";
        case 0x04:
            return "IP-in-IP";
        case 0x05:
            return "ST";
        case 0x06:
            return "TCP";
        case 0x07:
            return "CBT";
        case 0x08:
            return "EGP";
        case 0x09:
            return "IGP";
        case 0x0A:
            return "BBN-RCC-MON";
        case 0x0B:
            return "NVP-II";
        case 0x0C:
            return "PUP";
        case 0x0D:
            return "ARGUS";
        case 0x0E:
            return "EMCON";
        case 0x0F:
            return "XNET";
        case 0x10:
            return "CHAOS";
        case 0x11:
            return "UDP";
        case 0x12:
            return "MUX";
        case 0x13:
            return "DCN-MEAS";
        case 0x14:
            return "HMP";
        case 0x15:
            return "PRM";
        case 0x16:
            return "XNS-IDP";
        case 0x17:
            return "TRUNK-1";
        case 0x18:
            return "TRUNK-2";
        case 0x19:
            return "LEAF-1";
        case 0x1A:
            return "LEAF-2";
        case 0x1B:
            return "RDP";
        case 0x1C:
            return "IRTP";
        case 0x1D:
            return "ISO-TP4";
        case 0x1E:
            return "NETBLT";
        case 0x1F:
            return "MFE-NSP";
        case 0x20:
            return "MERIT-INP";
        case 0x21:
            return "DCCP";
        case 0x22:
            return "3PC";
        case 0x23:
            return "IDPR ";
        case 0x24:
            return "XTP";
        case 0x25:
            return "DDP";
        case 0x26:
            return "IDPR-CMTP";
        case 0x27:
            return "TP++";
        case 0x28:
            return "IL";
        case 0x29:
            return "IPv6";
        case 0x2A:
            return "SDRP";
        case 0x2B:
            return "IPv6-Route";
        case 0x2C:
            return "IPv6-Frag";
        case 0x2D:
            return "IDRP";
        case 0x2E:
            return "RSVP";
        case 0x2F:
            return "GRE";
        case 0x30:
            return "DSR";
        case 0x31:
            return "BNA";
        case 0x32:
            return "ESP";
        case 0x33:
            return "AH";
        case 0x34:
            return "I-NLSP";
        case 0x35:
            return "SwIPe";
        case 0x36:
            return "NARP";
        case 0x37:
            return "MOBILE";
        case 0x38:
            return "TLSP";
        case 0x39:
            return "SKIP";
        case 0x3A:
            return "IPv6-ICMP";
        case 0x3B:
            return "IPv6-NoNxt";
        case 0x3C:
            return "IPv6-Opts";
        case 0x3D:
            return "any host internal protocal";
        case 0x3E:
            return "CFTP";
        case 0x3F:
            return "any local network";
        case 0x40:
            return "SAT-EXPAK";
        case 0x41:
            return "KRYPTOLAN";
        case 0x42:
            return "PVD";
        case 0x43:
            return "IPPC";
        case 0x44:
            return "any distributed file system";
        case 0x45:
            return "SAT-MON";
        case 0x46:
            return "VISA";
        case 0x47:
            return "IPCU";
        case 0x48:
            return "CPNX";
        case 0x49:
            return "CPHB";
        case 0x4A:
            return "WSN";
        case 0x4B:
            return "PVP";
        case 0x4C:
            return "BR-SAT-MON";
        case 0x4D:
            return "SUN-ND";
        case 0x4E:
            return "WB-MON";
        case 0x4F:
            return "WB-EXPAK";
        case 0x50:
            return "ISO-IP";
        case 0x51:
            return "VMTP";
        case 0x52:
            return "SECURE-VMTP";
        case 0x53:
            return "VINES";
        case 0x54:
            return "IPTM/TTP this give two protocal:https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers";
        case 0x55:
            return "NSFNET-IGP";
        case 0x56:
            return "DGP";
        case 0x57:
            return "TCF";
        case 0x58:
            return "EIGRP";
        case 0x59:
            return "OSPF";
        case 0x5A:
            return "Sprite-RPC";
        case 0x5B:
            return "LARP";
        case 0x5C:
            return "MTP";
        case 0x5D:
            return "AX.25";
        case 0x5E:
            return "OS";
        case 0x5F:
            return "MICP";
        case 0x60:
            return "SCC-SP";
        case 0x61:
            return "ETHERIP";
        case 0x62:
            return "Encapsulaton Header";
        case 0x63:
            return "any private encryption scheme";
        case 0x64:
            return "GMTP";
        case 0x65:
            return "IFMP";
        case 0x66:
            return "PNNI";
        case 0x67:
            return "PIM";
        case 0x68:
            return "ARIS";
        case 0x69:
            return "SCPS";
        case 0x6A:
            return "QNX";
        case 0x6B:
            return "A/N";
        case 0x6C:
            return "IPComp";
        case 0x6D:
            return "SNP";
        case 0x6E:
            return "Compaq-Peer";
        case 0x6F:
            return "IPX-in-IP";
        case 0x70:
            return "VRRP";
        case 0x71:
            return "PGM";
        case 0x72:
            return "any 0-hop protocal";
        case 0x73:
            return "L2TP";
        case 0x74:
            return "DDX";
        case 0x75:
            return "IATP";
        case 0x76:
            return "STP";
        case 0x77:
            return "SRP";
        case 0x78:
            return "UTI";
        case 0x79:
            return "SMP";
        case 0x7A:
            return "SM";
        case 0x7B:
            return "PTP";
        case 0x7C:
            return "IS-IS over";
        case 0x7D:
            return "FIRE";
        case 0x7E:
            return "CRTP";
        case 0x7F:
            return "CRUDP";

        case 0x80:
            return "SSCOPMCE";
        case 0x81:
            return "IPLT";
        case 0x82:
            return "SPS";
        case 0x83:
            return "PIPE";
        case 0x84:
            return "SCTP";
        case 0x85:
            return "FC";
        case 0x86:
            return "RSVP-E2E-IGNORE";
        case 0x87:
            return "Mobility Header";
        case 0x88:
            return "UDPLite";
        case 0x89:
            return "MPLS-in-IP";
        case 0x8A:
            return "manet";
        case 0x8B:
            return "HIP";
        case 0x8C:
            return "Shim6";
        case 0x8D:
            return "WESP";
        case 0x8E:
            return "ROHC";
        case 0x8F:
            return "Ethernet";
        // 0x90--0xFC unassigned
        case 0xFF:
            return "Reserved";
        case 0xFD:
            return "0xFD-0xFE Use for experimentation and testing ";
        case 0xFE:
            return "0xFD-0xFE Use for experimentation and testing ";
        default:
            return "Unassigned";
    }
}
void analysis_struct(FORSHOWINFO *forshow,uchar *recv,uchar *s2,int start_index){  
    MAC_HEADER * mac_header = (MAC_HEADER *)(recv+start_index);
    sprintf(s2,"row:%d,%d",forshow->curr_row,forshow->end_row);
    strshow(s2);
    strshow("mac header:dest,src,protocal ");
    buffshow(mac_header->dest_mac,6);
    buffshow(mac_header->src_mac,6);
    buffshow(&(mac_header->protocal),2);
    
    IP_HEADER * ip_header = (IP_HEADER *)(mac_header+1);
    strshow("ip header:type,headlength,ttl,protocal,src_ip,dest_ip,identify,label_and_offset,length");
    buffshow(&(ip_header->ip_and_headlength),1);
    buffshow(&(ip_header->protocal),1);
    forshow->is_hex=0;// decimal system
    buffshow(&(ip_header->src_ip),4);
    buffshow(&(ip_header->dest_ip),4);
    forshow->is_hex=1;// hex system
    buffshow(&(ip_header->identify),2);
    buffshow(&(ip_header->label_and_offset),2);
    forshow->is_hex=0;// decimal system
    buffshow(&(ip_header->length),2);
    forshow->is_hex=1;// decimal system
    

    UDP_HEADER * udp_header= (UDP_HEADER *)(ip_header +1);
    strshow("udp header:src_port dest_port length checksum");
    forshow->is_hex=0;// decimal system
    buffshow(&(udp_header->src_port),2);
    buffshow(&(udp_header->dest_port),2);
    buffshow(&(udp_header->length),2);
    forshow->is_hex=1;// decimal system
    buffshow(&(udp_header->check_sum),2);

    DHCP_MESSAGE * dhcp_message = (DHCP_MESSAGE *)(udp_header+1);
    DHCP_INFO dhcp_info_recv={0,0,0,0,0,0,0,0,0};
    dhcp_options_ana(dhcp_message->options,&dhcp_info_recv);
    uchar s3[20];
    switch(dhcp_info_recv.message_type){
        case 1:
            sprintf(s3,"[DISCOVER]");
            break;
        case 2:
            sprintf(s3,"[OFFER]");
            break;
        case 3:
            sprintf(s3,"[REQUEST]");
            break;
        case 4://DHCP客户端收到DHCP服务器ACK应答报⽂后，通过地址冲突检测发现服务器分配的地址冲突或者由于其他原因导致不能使⽤，则
               //Decline（0x04）
               //会向DHCP服务器发送Decline请求报⽂，通知服务器所分配的IP地址不可⽤，以期获得新的IP地址。
            sprintf(s3,"[DECLINE]");
            break;
        case 5:
            sprintf(s3,"[ACK]");
            break;
        case 6:
            sprintf(s3,"[NAK]");
            break;
        case 7:
            sprintf(s3,"[RELEASSE]");
            break;
        case 8://DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息，则向DHCP服务器发送Inform请求报⽂；DHCP服务器在收到该
               //Inform（0x08）
               //报⽂后，将根据租约进⾏查找到相应的配置信息后，向DHCP客户端发送ACK应答报⽂。⽬前基本上不⽤了。
            sprintf(s3,"[INFORM]");
            break;

        default:
            sprintf(s3,"[OTHER]");
    }
    sprintf(s2,"DHCP %s message:ci,yi,si,gi addr options,dhcp_type",s3);
    strshow(s2);
    forshow->is_hex=0;
    buffshow(&(dhcp_message->ciaddr),4);
    buffshow(&(dhcp_message->yiaddr),4);
    buffshow(&(dhcp_message->siaddr),4);
    buffshow(&(dhcp_message->giaddr),4);
   

    //buffshow(dhcp_message->options,dhcp_info_recv.length);
    strshow("dhcp_options:server_identifier,router,subnet_mask,domain_name_server,lease_time,length");
                            /*
    uchar message_type;
    long client_ip_addr;
    int length;
    long server_identifier;
    long lease_time;
    long subnet_mask;
    long router;
    long domain_name_server;
    uchar *domain_name;
    */
    buffshow(&(dhcp_info_recv.server_identifier),4);
    buffshow(&(dhcp_info_recv.router),4);
    buffshow(&(dhcp_info_recv.subnet_mask),4);
    buffshow(&(dhcp_info_recv.domain_name_server),4);
    buffshow(&(dhcp_info_recv.lease_time),4);
    buffshow(&(dhcp_info_recv.length),4);



    forshow->is_hex=1;

}
int dhcp_options_ana(uchar *options,DHCP_INFO * dhcp_info){
    /*
    uchar message_type;
    long client_ip_addr;
    int length;
    long server_identifier;
    long lease_time;
    long subnet_mask;
    long router;
    long domain_name_server;
    uchar *domain_name;
    */
    int i=0;
    int length=1;
    int tmp_len=1;

    for(i=0;i<100;i++){

        switch(*(options+length-1)){
            case 1:// subnet mask
                dhcp_info->subnet_mask=*((long *)(options+length+1));
                break;
            case 2:
                break;
            case 3:// router
                dhcp_info->router=*((long *)(options+length+1));
                break;
            case 4:
                break;
            case 5:
                break;
            case 6:// domain name server
                dhcp_info->domain_name_server=*((long *)(options+length+1));
                break;
            case 15: // domain name
                break;
            case 51: // ip addr lease time
                dhcp_info->lease_time=*((long *)(options+length+1));
                break;
            
            case 53:
                dhcp_info->message_type=*(options+length+1);
                //return dhcp_info->message_type;
                break;
            case 54: // server identifier
                dhcp_info->server_identifier=*((long *)(options+length+1));
                break;
            
            default:
                break;

        }
        tmp_len=*(options+length);
        length=length+tmp_len+2;
        if((*(options+length))==0 && (*(options+length-1))==0xff){
            length=length-2;
            break;
        }

    }
    dhcp_info->length=length+1;
   
    return 0;
}
int src_port_filter(FORSHOWINFO * forshow,uchar *recv,int start_index,short port){
    MAC_HEADER * mac_header = (MAC_HEADER *)(recv+start_index);
    if(mac_header->protocal==hxl(0x0800)){
        IP_HEADER * ip_header = (IP_HEADER *)(mac_header+1);
        if(ip_header->protocal==0x11){
            UDP_HEADER * udp_header= (UDP_HEADER *)(ip_header +1);
            if(udp_header->src_port==hxl(port)){
                return 1;
            }
        }
    }
    return 0;

}
/*
int dhcp_message_filter(uchar *recv,int start_index){
    MAC_HEADER * mac_header = (MAC_HEADER *)(recv+start_index);
    if(mac_header->protocal==hxl(0x0800)){
        IP_HEADER * ip_header = (IP_HEADER *)(mac_header+1);
        if(ip_header->protocal==0x11){
            UDP_HEADER * udp_header= (UDP_HEADER *)(ip_header +1);
            DHCP_MESSAGE * dm = (DHCP_MESSAGE *)(udp_header+1);
            return dhcp_options_ana(dm->options);
        }
    }
    return 0;
}
*/
int get_dhcp_message(uchar *recv,int start_index){
    MAC_HEADER * mac_header = (MAC_HEADER *)(recv+start_index);
    if(mac_header->protocal==hxl(0x0800)){
        IP_HEADER * ip_header = (IP_HEADER *)(mac_header+1);
        if(ip_header->protocal==0x11){
            UDP_HEADER * udp_header= (UDP_HEADER *)(ip_header +1);
            DHCP_MESSAGE * dm = (DHCP_MESSAGE *)(udp_header+1);
            return dm;
        }
    }
    return 0;
}


ARP_PACKET * create_arp_packet(struct MEMMAN *memman,DHCP_INFO * dhcp_info,IP_ADDR *ipa,MAC_ADDR *maca){
    
    ARP_PACKET *arp_p= (ARP_PACKET *) memman_alloc_4k(memman, sizeof(ARP_PACKET));
    init_mac_header(arp_p,0x0806);
    init_arp_packet(arp_p,dhcp_info,ipa,maca);
    return arp_p;
}
MAC_PACKAGE * create_dhcp_pacakge(struct MEMMAN *memman,DHCP_INFO* dhcp_info){
    
    MAC_PACKAGE *mac_p= (MAC_PACKAGE *) memman_alloc_4k(memman, sizeof(MAC_PACKAGE));

     // MAC header
    init_mac_header(mac_p,0x0800);
    // IP header
    init_ip_package(&((mac_p->ip).header));
    mac_p->ip.header.head_checksum=calculate_checksum((unsigned short *)(&(mac_p->ip.header)),sizeof(mac_p->ip.header)/2);
    
    // UDP header
    mac_p->ip.udp.header.src_port=hxl(68);
    mac_p->ip.udp.header.dest_port=hxl(67);
    mac_p->ip.udp.header.length=hxl(sizeof(mac_p->ip.udp)-4);
    //mac_p->ip.udp.lenth=sizeof(mac_p->ip.udp)-4;
    mac_p->ip.udp.header.check_sum=0;

    struct UDP_PERSDO_PACKAGE *udp_persdo=(struct UDP_PERSDO_PACKAGE *)memman_alloc_4k(memman,sizeof(struct UDP_PERSDO_PACKAGE));
    udp_persdo->src_ip = 0x00000000;
    udp_persdo->dest_ip = 0xffffffff;
    udp_persdo->zeros=0x00;
    udp_persdo->protocal = 17;
    udp_persdo->length = sizeof(struct UDP_PERSDO_PACKAGE);
    
    
    // DHCP message header
    init_message_package(&(mac_p->ip.udp.message),dhcp_info);
    //init_message_package(&(mac_p->ip.udp.message));
    udp_persdo->message=mac_p->ip.udp.message;
    mac_p->ip.udp.header.check_sum = calculate_checksum((short *)udp_persdo, sizeof(*udp_persdo)/2);
    // 释放UPD伪包的内存
    memman_free(memman,&(udp_persdo),sizeof(*(udp_persdo)));
    return mac_p;
}
